package com.ruoyi.system.service;

import java.util.*;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.ExcelUtils;
import com.ruoyi.system.domain.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class AsyncService {
    @Autowired
    private ISysCompanyThingsboardService sysCompanyThingsboardService;

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private IDeviceTerminalService deviceTerminalService;

    @Autowired
    private IDeviceTerminalMqttService deviceTerminalMqttService;

    @Autowired
    private IDeviceTerminalHttpService deviceTerminalHttpService;

    @Autowired
    private IDeviceTerminalCoapService deviceTerminalCoapService;

    @Autowired
    private IDeviceTerminalLwm2mService deviceTerminalLwm2mService;

    @Autowired
    private IProjectService projectService;

    @Autowired
    private IAsyncDetailService asyncDetailService;

    @Autowired
    private IDevicePointCheckConfigService devicePointCheckConfigService;

    @Async
    public void injectProjects(String tid, String filename, String owner, Long companyId) {
        try {
            String path = RuoYiConfig.getUploadPath();
            List<JSONObject> items = ExcelUtils.load(path + "/" + filename);
            // List<JSONObject> items = ExcelUtils.load(filename);
            if (items == null || items.size() == 0) {
                asyncDetailService.update(tid, 2, "数据格式不正确");
                return;
            }
            JSONArray results = new JSONArray();
            String createBy = owner;
            for (int i = 0; i < items.size(); i++) {
                JSONObject item = items.get(i);
                log.info("{}", item);
                JSONObject result = new JSONObject();
                try {
                    Map<String, Object> parsed = projectService.parseInjectionItem(item, companyId);
                    Project project = (Project)parsed.get("project");
                    if (project == null) {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, parsed.get("message")));
                        results.add(result);
                        continue;
                    }
                    project.setCompanyId(companyId);
                    project.setCreateBy(createBy);
                    project.setCreateTime(new Date());
                    Map<String, Object> existance = projectService.findExistance(project);
                    if (existance != null) {
                        Object name_exists = existance.get("name_exists");
                        if (name_exists != null && Integer.parseInt(name_exists.toString()) > 0) {
                            result.put("done", false);
                            result.put("message", String.format("第%d行：%s", i + 2, "项目名称已经存在"));
                            results.add(result);
                            continue;
                        }
                        Object code_exists = existance.get("code_exists");
                        if (code_exists != null && Integer.parseInt(code_exists.toString()) > 0) {
                            result.put("done", false);
                            result.put("message", String.format("第%d行：%s", i + 2, "合同号已经存在"));
                            results.add(result);
                            continue;
                        }
                        Object peer_code_exists = existance.get("peer_code_exists");
                        if (peer_code_exists != null && Integer.parseInt(peer_code_exists.toString()) > 0) {
                            result.put("done", false);
                            result.put("message", String.format("第%d行：%s", i + 2, "客户合同号已经存在"));
                            results.add(result);
                            continue;
                        }
                    }
                    Integer id = projectService.create(project);
                    if (id == null) {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                        results.add(result);
                    } else {
                        result.put("done", true);
                        result.put("message", String.format("第%d行：%s", i + 2, "操作成功"));
                        result.put("data", project);
                        results.add(result);
                    }
                } catch (Exception e) {
                    log.info("",e);
                    StackTraceElement[] traces = e.getStackTrace();
                    for (StackTraceElement trace : traces) {
                        log.debug(trace.toString());
                    }
                    result.put("done", false);
                    result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                    results.add(result);
                }
            }
            asyncDetailService.update(tid, 1, results.toJSONString());
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
            asyncDetailService.update(tid, 2, "操作失败");
        }
    }

    @Async
    public void injectDevices(String tid, String filename, String owner, Long companyId) {
        try {
            String path = RuoYiConfig.getUploadPath();
            List<JSONObject> items = ExcelUtils.load(path + "/" + filename);
            if (items == null || items.size() == 0) {
                asyncDetailService.update(tid, 2, "数据格式不正确");
                return;
            }
            JSONArray results = new JSONArray();
            SysCompanyThingsboard sysCompanyThingsboard = sysCompanyThingsboardService.selectSysCompanyThingsboardByCompanyId(companyId);
            String createBy = owner;
            for (int i = 0; i < items.size(); i++) {
                JSONObject item = items.get(i);
                log.info("{}", item);
                JSONObject result = new JSONObject();
                try {
                    Map<String, Object> parsed = deviceService.parseInjectionItem(item, companyId);
                    Device device = (Device)parsed.get("device");
                    if (device == null) {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, parsed.get("message")));
                        results.add(result);
                        continue;
                    }
                    device.setCompanyId(companyId);
                    device.setCreateBy(createBy);
                    device.setCreateTime(new Date());
                    Map<String, Object> existance = deviceService.findExistance(device);
                    if (existance != null) {
                        Object name_exists = existance.get("name_exists");
                        // if (name_exists != null && Integer.parseInt(name_exists.toString()) > 0) {
                        //     result.put("done", false);
                        //     result.put("message", "产品名称已经存在");
                        //     results.add(result);
                        //     continue;
                        // }
                        Object sn_exists = existance.get("sn_exists");
                        if (sn_exists != null && Integer.parseInt(sn_exists.toString()) > 0) {
                            result.put("done", false);
                            result.put("message", String.format("第%d行：%s", i + 2, "产品代码已经存在"));
                            results.add(result);
                            continue;
                        }
                    }
                    Integer id = deviceService.create(device, sysCompanyThingsboard);
                    if (id != null) {
                        @SuppressWarnings("unchecked")
                        List<String> terminalSnList = (List<String>)parsed.get("terminalSnList");
                        @SuppressWarnings("unchecked")
                        List<JSONObject> terminalCredentialsList = (List<JSONObject>)parsed.get("terminalCredentialsList");
                        List<String> failed = new ArrayList<>();
                        for (DeviceTerminal deviceTerminal : device.getTerminals()) {
                            Integer number = deviceTerminal.getProductTerminalNumber();
                            String sn = terminalSnList.get(number - 1);
                            if (sn != null) {
                                DeviceTerminal input = new DeviceTerminal();
                                input.setId(deviceTerminal.getId());
                                input.setSn(sn);
                                deviceTerminalService.update(input);
                            }
                            Integer deviceTerminalId = deviceTerminal.getId();
                            String tbDeviceId = deviceTerminal.getTbDeviceId();
                            Object credetials = terminalCredentialsList.get(number - 1);
                            if (credetials != null) {
                                Integer ret = null;
                                String protocol = deviceTerminal.getProductTerminalProtocol();
                                if (protocol.equals("MQTT")) {
                                    MqttCredentials mqttCredentials = (MqttCredentials)credetials;
                                    mqttCredentials.setTbDeviceId(tbDeviceId);
                                    mqttCredentials.setDeviceTerminalId(deviceTerminalId);
                                    mqttCredentials.setCompanyId(companyId);
                                    ret = deviceTerminalMqttService.createCredentials(mqttCredentials, sysCompanyThingsboard);
                                } else if (protocol.equals("HTTP")) {
                                    HttpCredentials httpCredentials = (HttpCredentials)credetials;
                                    httpCredentials.setTbDeviceId(tbDeviceId);
                                    httpCredentials.setDeviceTerminalId(deviceTerminalId);
                                    httpCredentials.setCompanyId(companyId);
                                    ret = deviceTerminalHttpService.createCredentials(httpCredentials, sysCompanyThingsboard);
                                } else if (protocol.equals("CoAP")) {
                                    CoapCredentials coapCredentials = (CoapCredentials)credetials;
                                    coapCredentials.setTbDeviceId(tbDeviceId);
                                    coapCredentials.setDeviceTerminalId(deviceTerminalId);
                                    coapCredentials.setCompanyId(companyId);
                                    ret = deviceTerminalCoapService.createCredentials(coapCredentials, sysCompanyThingsboard);
                                } else if (protocol.equals("LwM2M")) {
                                    Lwm2mCredentials lwm2mCredentials = (Lwm2mCredentials)credetials;
                                    lwm2mCredentials.setTbDeviceId(tbDeviceId);
                                    lwm2mCredentials.setDeviceTerminalId(deviceTerminalId);
                                    lwm2mCredentials.setCompanyId(companyId);
                                    ret = deviceTerminalLwm2mService.createCredentials(lwm2mCredentials, sysCompanyThingsboard);
                                }
                                if (ret == null) {
                                    failed.add(number.toString());
                                }
                            }
                        }
                        if (failed.size() > 0) {
                            result.put("done", false);
                            result.put("message", String.format("第%d行：传感器%s配置失败", i + 2, String.join(", ", failed)));
                            result.put("data", device);
                            results.add(result);
                        } else {
                            result.put("done", true);
                            result.put("message", String.format("第%d行：%s", i + 2, "操作成功"));
                            result.put("data", device);
                            results.add(result);
                        }
                    } else {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                        results.add(result);
                    }
                } catch (Exception e) {
                    log.info("",e);
                    StackTraceElement[] traces = e.getStackTrace();
                    for (StackTraceElement trace : traces) {
                        log.debug(trace.toString());
                    }
                    result.put("done", false);
                    result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                    results.add(result);
                }
            }
            asyncDetailService.update(tid, 1, results.toJSONString());
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
            asyncDetailService.update(tid, 2, "操作失败");
        }
    }

    @Async
    public void injectDevicesPointCheckConfig(String tid, String filename, String owner, Long companyId, Integer deviceId) {
        try {
            String path = RuoYiConfig.getUploadPath();
//            String path = "D:/data";

            List<JSONObject> items = ExcelUtils.load(path + "/" + filename);
//             List<JSONObject> items = ExcelUtils.load(filename);
            if (items == null || items.size() == 0) {
                asyncDetailService.update(tid, 2, "数据格式不正确");
                return;
            }
            JSONArray results = new JSONArray();
            String createBy = owner;
            for (int i = 0; i < items.size(); i++) {
                JSONObject item = items.get(i);
                log.info("{}", item);
                JSONObject result = new JSONObject();
                try {
                    Map<String, Object> parsed = devicePointCheckConfigService.parseInjectionItem(item, companyId);
                    DevicePointCheckConfig devicePointCheckConfig = (DevicePointCheckConfig)parsed.get("devicePointCheckConfig");
                    if (devicePointCheckConfig == null) {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, parsed.get("message")));
                        results.add(result);
                        continue;
                    }
                    devicePointCheckConfig.setCompanyId(companyId);
                    devicePointCheckConfig.setDeviceId(deviceId);
                    devicePointCheckConfig.setCreateBy(createBy);
                    devicePointCheckConfig.setCreateTime(new Date());
                    Map<String, Object> existance = new HashMap<>();
                    if(devicePointCheckConfig.getCategory()==0){
                       existance = devicePointCheckConfigService.findExistanceItem(devicePointCheckConfig);
                    }else{
                       existance = devicePointCheckConfigService.findExistance(devicePointCheckConfig);
                    }

                    if (existance != null) {
                        Object message = existance.get("message");
                            result.put("done", false);
                            result.put("message", String.format("第%d行：%s", i + 2, message));
                            results.add(result);
                            continue;
                    }
                    if (devicePointCheckConfigService.add(devicePointCheckConfig)) {
                        result.put("done", true);
                        result.put("message", String.format("第%d行：%s", i + 2, "操作成功"));
                        result.put("data", devicePointCheckConfig);
                        results.add(result);
                    } else {
                        result.put("done", false);
                        result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                        results.add(result);
                    }
                } catch (Exception e) {
                    log.info("",e);
                    StackTraceElement[] traces = e.getStackTrace();
                    for (StackTraceElement trace : traces) {
                        log.debug(trace.toString());
                    }
                    result.put("done", false);
                    result.put("message", String.format("第%d行：%s", i + 2, "操作失败"));
                    results.add(result);
                }
            }
            asyncDetailService.update(tid, 1, results.toJSONString());
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
            asyncDetailService.update(tid, 2, "操作失败");
        }
    }
}
